#include "sock.hpp"
#include "common.hpp"
#include "addr.hpp"
#include <unistd.h>
#include <algorithm>
#include<sys/epoll.h>
class pollserver
{

    const static int defaultfd = -1;
    const static int size=500;

public:
    pollserver(int port) : _is_running(0), _listenfd(make_unique<Tcpsocket>())
    {  
        _listenfd->arrangesock(port);

        int p=epoll_create(size);
       if(p>0) {
        _epfd=p;
           use_log(loglevel::DEBUG) << "epoll_create sussess!";
       }
       else {
        use_log(loglevel::DEBUG) << "epoll_create fail!";
        exit(EPOLL_FAIL);
       }
         struct epoll_event ev;
         ev.events=EPOLLIN;
         ev.data.fd=_listenfd->Fd();
       int n= epoll_ctl(_epfd,EPOLL_CTL_ADD,_listenfd->Fd(),&ev);
        if(n>=0) {
             use_log(loglevel::DEBUG) << "epoll_ctl sussess!";
        }
        else {
            cout<<n<<endl;
             use_log(loglevel::DEBUG) << "epoll_ctl  fail!";
        }
    }

    void start()
    {
        _is_running = 1;
        while (_is_running)
        {
            int n=epoll_wait(_epfd,_evs,size,-1);//阻塞等待
            if (n > 0)
            {
                use_log(loglevel::DEBUG) << "读（写）事件就绪!";
                Dispatcher(n);
            }
            else if (n == 0)
            {

                use_log(loglevel::DEBUG) << "等待超时!";
                break;
            }
            else
            {
                cout << "错误 ：" << n << endl;
                use_log(loglevel::DEBUG) << "epoll 错误";
                break;
            }
        }
    }

    void Dispatcher(int n)
    {
        for (int i = 0; i <n; i++)
        {
            if (_evs[i].events&EPOLLIN>0)//读事件就绪进行处理
            {

                if (_evs[i].data.fd == _listenfd->Fd())
                    Acceper(); // 去等待队列接收新链接
                else
                    Recver(_evs[i].data.fd); // 读取对应缓冲区数据
            }
        }
    }

    void Acceper()
    {
        inetaddr client;
        int newfd = _listenfd->Accept(&client);
        struct epoll_event ev;    
        ev.events=EPOLLIN;
         ev.data.fd=newfd;  
         int n= epoll_ctl(_epfd,EPOLL_CTL_ADD,newfd,&ev);  
        if(n<0)  use_log(loglevel::DEBUG) << "epoll_ctl  fail!";
        //这里默认epoll模型暂时不会满
            else use_log(loglevel::DEBUG) << "epoll new client ";
        
    }

    void Recver(int fd)
    {
        char buf[1024] = {0};
        int n = recv(fd, buf, sizeof(buf) - 1, 0);
        if (n > 0)
        {
            buf[n] = 0;
            cout << " client say @  : " << buf << endl;
        }
        else if (n == 0)
        {
            use_log(loglevel::DEBUG) << "client exit";
           //epoll模型无法维护一个无效的fd；因此先从epoll模型把fd移除再关闭fd
             int n= epoll_ctl(_epfd,EPOLL_CTL_DEL,fd,nullptr);  //epoll_event 结构体不知道就传nullptr
             if(n>=0){
                     use_log(loglevel::DEBUG) << "delete clientfd from epoll";
             }
             close(fd);
        }

        else
        {

            use_log(loglevel::DEBUG) << "Recv error";
            int n= epoll_ctl(_epfd,EPOLL_CTL_DEL,fd,nullptr);  //epoll_event 结构体不知道就传nullptr
             if(n>=0){
                     use_log(loglevel::DEBUG) << "delete clientfd from epoll";
             }
             close(fd);
           
        }
    }
    void stop()
    {
        _is_running = 0;
        if(_epfd>0){
            close(_epfd);
        }
        _listenfd->Close();
    }
    ~pollserver() {}

private:
    bool _is_running;
    unique_ptr<Socket> _listenfd;
    int _epfd;
    struct epoll_event _evs[size];
};
